/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.epam.expertsys;
//import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Iterator;
import java.io.*;

/**
 *
 * @author Admin
 */
public class ExpertEvaluations {

    /**
     * Runs direct derivation process at RulesKnown and FactsKnown instances.
     * Attempts to log derivation process to file named logFileName.
     * If during the derivation there is attempt to redefine a variable,
     * throws VariableRedefinedException.
     * @param logFileName
     * @throws VariableRedefinedException
     */
    public static void directDerivation(String logFileName)
            throws VariableRedefinedException {
        boolean hasStream = true;
        FileWriter fileWriter;
        BufferedWriter bufWriter;
        PrintWriter printWriter = null;

        try {
            fileWriter = new FileWriter(logFileName);
            bufWriter = new BufferedWriter(fileWriter);
            printWriter = new PrintWriter(bufWriter);
        } catch (IOException e) {
            hasStream = false;
            System.out.println("StreamProblem");
        }
        LinkedList<String> varQueue = new LinkedList<String>();
        RulesKnown Rules = RulesKnown.getInstance();
        FactsKnown Facts = FactsKnown.getInstance();
        int rulesNum = Rules.getNumberRules();

        for (int index = 0;
                index < Facts.numberFacts();
                index++) {
            varQueue.add(Facts.getFact(index).getVarName());
        }

        int varIndex = 0;

        do {
            //String currVariable = (String)varIterator.next();

            for (int ruleIndex = 0; ruleIndex < rulesNum; ruleIndex++) {
                Rule currRule = Rules.getRule(ruleIndex);
                boolean trueFlag = true;
                //System.out.println("ruleIndex = " + ruleIndex);

                for (int condIndex = 0;
                        condIndex < currRule.numConditions();
                        condIndex++) {
                    //  System.out.println("condIndex = " + condIndex +
                    //          " bool " + trueFlag);
                    if (!(Facts.getFacts().contains(
                            currRule.getCondition(condIndex)))) {
                        trueFlag = false;
                    }
                }

                //System.out.println("trueflag = " + trueFlag);

                if (trueFlag == true) {
                    if ((hasStream == true)
                            && !(Facts.isDefined(currRule.getConsequence().getVarName()))) {
                        for (int indCond = 0;
                                indCond < currRule.numConditions();
                                indCond++) {
                            printWriter.print("("
                                    + currRule.getCondition(indCond).getVarName()
                                    + " = "
                                    + currRule.getCondition(indCond).getVarValue()
                                    + ")");
                            if (indCond != (currRule.numConditions() - 1)) {
                                printWriter.println("/\\");
                            }
                        }
                        printWriter.print(" => ");
                        printWriter.println("("
                                + currRule.getConsequence().getVarName()
                                + " = "
                                + currRule.getConsequence().getVarValue()
                                + ")");
                        printWriter.println("******************************");


                    }

                    Facts.addFact(currRule.getConsequence());
                    varQueue.add(currRule.getConsequence().getVarName());

                }
            }

            varIndex++;
        } while (varIndex < Facts.numberFacts());
        if (hasStream) {
            printWriter.close();
        }
    }
}
